1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
| from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import struct
data = [0x0b, 0xdf, 0x65, 0x3c, 0x6e, 0x13, 0xab, 0x6e, 0xb6, 0x3c, 0x0a, 0x7f, 0xf7, 0x04, 0x2d, 0x3a, 0xf0, 0xd4, 0x7f, 0x18, 0xb0, 0xc8, 0x79, 0xcd, 0xf0, 0xdf, 0x95, 0xa1, 0x24, 0x0f, 0xab, 0x42]
aes_iv = bytes(data[16:]) aes_key = bytes(data[:16])
print(f"AES Key: {aes_key.hex()}") print(f"AES IV: {aes_iv.hex()}")
aes_enc_data = bytes([ 0xb3, 0x9f, 0xc8, 0xe2, 0x35, 0xfa, 0xd2, 0x2c, 0x3a, 0xd1, 0x6f, 0x37, 0xe7, 0xd9, 0x9c, 0x6a, 0x0e, 0xb0, 0x42, 0xc6, 0x7c, 0xe9, 0x11, 0x44, 0xaf, 0x3d, 0x28, 0xda, 0xe1, 0xb5, 0x45, 0x80, 0x5b, 0xeb, 0x4d, 0x32, 0xee, 0x24, 0xc4, 0xd8, 0x0d, 0x2e, 0x61, 0xfd, 0x4a, 0xe1, 0x6d, 0x99, 0x6c, 0xac, 0x6a, 0x15, 0xc2, 0x78, 0x0a, 0x38, 0x00, 0x94, 0x38, 0x59, 0x51, 0xed, 0xc7, 0xa4, 0xed, 0x6f, 0x60, 0xe0, 0xb9, 0xf3, 0x4d, 0xb1, 0x25, 0x37, 0x93, 0x1e, 0xf6, 0x8b, 0x0e, 0x6b, 0x62, 0x42, 0x87, 0x5a, 0x41, 0xae, 0xc5, 0x98, 0x80, 0xb0, 0x1a, 0x85, 0x3d, 0x21, 0xb4, 0x5a, 0x5e, 0xf9, 0x09, 0xfa, 0xd3, 0x32, 0x58, 0x56, 0xf8, 0xed, 0xeb, 0x48, 0x83, 0x7d, 0xc9, 0x22, 0x8f, 0x97, 0x4e, 0xf7, 0x17, 0x25, 0x48, 0x82, 0x15, 0xe2, 0xa0, 0x84, 0x4e, 0x48, 0x05, 0xff, 0x59, 0xe3, 0xf5, 0xcb, 0x0b, 0xdc, 0x18, 0x54, 0x4f, 0xe5, 0xe5, 0x19, 0x1c, 0x2d, 0xb2, 0xf7, 0xa7, 0xee, 0xae, 0x00, 0xb1, 0xb9, 0x54, 0x48, 0x68, 0xe5, 0xed, 0x31, 0x12, 0xf4, 0x8b, 0xd5, 0x6c, 0xe7, 0x3e, 0x26, 0x3c, 0xa1, 0x32, 0x87, 0xf3, 0x19, 0x84, 0x10, 0x6a, 0x00, 0xd5, 0x68, 0x38, 0x01, 0x7a, 0x89, 0xc0, 0x12, 0xbc, 0x19, 0xdf, 0x91, 0x86, 0xdd, 0x15, 0x20, 0xfd, 0xeb, 0xa5, 0xc8, 0xbc, 0x93, 0xf1, 0xbb, 0x96, 0x81, 0x5d, 0xb4, 0xeb, 0x82, 0x5a, 0x5a, 0x5b, 0x72, 0x25, 0x61, 0x8a, 0x6e, 0x3e, 0x89, 0x77, 0x22, 0xa8, 0x7e, 0xb9, 0xcd, 0x01, 0x86, 0x71, 0xeb, 0xf1, 0xa1, 0x4b, 0x4b, 0x81, 0x34, 0x35, 0x9b, 0x69, 0x53, 0xa4, 0xb3, 0x6c, 0xc0, 0x44, 0xc8, 0x9b, 0x8b, 0x89, 0x72, 0xd7, 0x54, 0x03, 0x8d, 0x2c, 0x8e, 0x4c, 0x01, 0x5a, 0x6f, 0x24, 0x3c, 0x3d, 0x13, 0x4c, 0x83, 0x2a, 0x50, 0xac, 0x94, 0x7f, 0xb2, 0x85, 0xb0, 0x9e, 0x8f, 0x54, 0x44, 0x01, 0x1d, 0xcc, 0xd7, 0x52, 0x16, 0xad, 0x7c, 0x30, 0x37, 0x61, 0x2b, 0x91, 0x8b, 0xe8, 0x82, 0x5a, 0x25, 0x15, 0x90, 0xb4, 0xde, 0x2c, 0xec, 0x6e, 0x5c, 0xd3, 0xa9, 0x8f, 0x0c, 0x73, 0x04 ][:256])
print(f"\n=== Step 1: AES-CBC 解密 ===") print(f"密文长度: {len(aes_enc_data)} bytes")
aes_cipher = AES.new(aes_key, AES.MODE_CBC, aes_iv) try: aes_decrypted = unpad(aes_cipher.decrypt(aes_enc_data), AES.block_size) print("成功 unpad") except ValueError as e: print(f"Unpad 失败: {e}, 使用原始解密结果") aes_cipher = AES.new(aes_key, AES.MODE_CBC, aes_iv) aes_decrypted = aes_cipher.decrypt(aes_enc_data)
print(f"AES 解密长度: {len(aes_decrypted)} bytes") print(f"AES 解密结果 (前64字节): {aes_decrypted[:64].hex()}")
if len(aes_decrypted) % 4 != 0: print(f"警告: 解密结果长度不是4的倍数!")
print("\n=== Step 2: ChaCha20 解密 ===")
CHACHA_CONSTANTS = [1768978533, 1948281188, 1701603695, 2054299764]
CHACHA_KEY = [ 2778944304, 2710134585, 1612543563, 1172917921, 3846223579, 2389091675, 972033108, 274738666 ]
CHACHA_NONCE = [888566743, 3797923964, 2911175433]
def rotl(x, n): """32位循环左移""" return ((x << n) & 0xFFFFFFFF) | (x >> (32 - n))
def quarter_round(state, a, b, c, d): """ChaCha20 Quarter Round - 完全按照 shader 实现""" state[a] = (state[a] + state[b]) & 0xFFFFFFFF state[d] = state[d] ^ state[a] state[d] = rotl(state[d], 16) state[c] = (state[c] + state[d]) & 0xFFFFFFFF state[b] = state[b] ^ state[c] state[b] = rotl(state[b], 12) state[a] = (state[a] + state[b]) & 0xFFFFFFFF state[d] = state[d] ^ state[a] state[d] = rotl(state[d], 8) state[c] = (state[c] + state[d]) & 0xFFFFFFFF state[b] = state[b] ^ state[c] state[b] = rotl(state[b], 7)
def chacha20_block(counter): """生成一个 ChaCha20 块 - 完全按照 shader xY 函数""" state = [0] * 16 state[0:4] = CHACHA_CONSTANTS state[4:12] = CHACHA_KEY state[12] = counter state[13:16] = CHACHA_NONCE working_state = state.copy() for _ in range(10): quarter_round(working_state, 0, 1, 2, 3) quarter_round(working_state, 4, 5, 6, 7) quarter_round(working_state, 8, 9, 10, 11) quarter_round(working_state, 12, 13, 14, 15) quarter_round(working_state, 0, 4, 8, 12) quarter_round(working_state, 1, 5, 9, 13) quarter_round(working_state, 2, 6, 10, 14) quarter_round(working_state, 3, 7, 11, 15) quarter_round(working_state, 0, 5, 10, 15) quarter_round(working_state, 1, 6, 11, 12) quarter_round(working_state, 2, 7, 8, 13) quarter_round(working_state, 3, 4, 9, 14) for i in range(16): working_state[i] = (working_state[i] + state[i]) & 0xFFFFFFFF return working_state
def chacha20_decrypt(ciphertext_bytes): """解密 - 按照 shader m_inner 函数的逻辑""" num_u32 = len(ciphertext_bytes) // 4 ciphertext_u32 = list(struct.unpack(f'<{num_u32}I', ciphertext_bytes[:num_u32*4])) plaintext_u32 = [] for block_idx in range((num_u32 + 15) // 16): offset = block_idx * 16 keystream = chacha20_block(block_idx) for i in range(16): if offset + i < num_u32: plaintext_u32.append(ciphertext_u32[offset + i] ^ keystream[i]) return plaintext_u32
password_u32 = chacha20_decrypt(aes_decrypted) print(f"ChaCha20 解密得到 {len(password_u32)} 个 uint32")
password_bytes = struct.pack(f'<{len(password_u32)}I', *password_u32) print(f"解密结果长度: {len(password_bytes)} bytes") print(f"解密结果 (hex): {password_bytes.hex()}") print(f"解密结果 (前64字节): {password_bytes[:64]}")
print(f"\n=== 解码尝试 ===")
try: password_str = password_bytes.rstrip(b'\x00').decode('utf-8') print(f"UTF-8: {password_str}") except: print("UTF-8 解码失败")
printable = '' for b in password_bytes: if 32 <= b < 127: printable += chr(b) elif b == 0: break else: printable += f'\\x{b:02x}' print(f"可打印字符: {printable}")
if b'flag' in password_bytes.lower(): print("发现 'flag' 字样!") if b'xctf' in password_bytes.lower(): print("发现 'xctf' 字样!")
print(f"\n不同偏移的可打印字符:") for offset in [0, 4, 8, 12, 16]: snippet = password_bytes[offset:offset+32] readable = ''.join(chr(b) if 32 <= b < 127 else '.' for b in snippet) print(f"Offset {offset:2d}: {readable}")
|